﻿using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using YNTK.Common.Const;
using YNTK.Common.Enum;
using YNTK.Common.Filter;
using YNTK.Common.Util;
using YNTK.Data.MongoDB.Repositorie;
using YNTK.DataEncryption;
using YNTK.Dependency;
using YNTK.DynamicApiController;
using YNTK.Employees.Entitys.Entity;
using YNTK.EventBridge;
using YNTK.FriendlyException;
using YNTK.LinqBuilder;
using YNTK.Mapster;
using YNTK.System.Entitys.Dto.Common;
using YNTK.System.Entitys.Dto.Permission.User;
using YNTK.System.Entitys.Permission;
using YNTK.System.Interfaces.Permission;

namespace YNTK.System.Service.Permission
{
    /// <summary>
    /// 用户服务的实现
    /// 版 本：V1.0.0
    /// 版 权：云南通科科技有限公司（https://www.yntkkj.com）
    /// 作 者：李仕鹏
    /// 日 期：2022-10-05
    /// </summary>
    [ApiDescriptionSettings(Tag = "用户管理", Name = "TkUsers", Order = 793)]
    [Route("api/[controller]")]
    public class TkUsersService: ITkUsersService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<UserEntity> _tkUserRepository;//用户仓储
        private readonly IMongoDBRepository<UserEntity> _tkUserMongoDbRepository;//用户mongodb仓储
        private readonly ISqlSugarRepository<MechanismEntity> _mechanismRepository;//机构仓储
        private readonly IMongoDBRepository<MechanismEntity> _mechanismMongoDbRepository;//机构mongodb仓储
        private readonly ITkRoleService _tkRoleService;//角色服务
        private readonly IOrganizeService _organizeService;//组织服务
        private readonly HttpContext _httpContext;

        private readonly string _users = "base_users";//mongodb中用户数据集名称
        private readonly string _collectionName = "base_mechanisms";//mongodb中机构数据集名称

        /// <summary>
        /// 构造方法依赖注入
        /// </summary>
        /// <param name="tkUserRepository">用户仓储</param>
        /// <param name="tkUserMongoDbRepository">用户mongodb仓储</param>
        /// <param name="mechanismMongoDbRepository">机构mongodb仓储</param>
        /// <param name="mechanismRepository">机构仓储</param>
        /// <param name="tkRoleService">角色服务</param>
        /// <param name="organizeService">组织服务</param>
        public TkUsersService(ISqlSugarRepository<UserEntity> tkUserRepository,
            IMongoDBRepository<UserEntity> tkUserMongoDbRepository,
            ISqlSugarRepository<MechanismEntity> mechanismRepository,
            IMongoDBRepository<MechanismEntity> mechanismMongoDbRepository,
            ITkRoleService tkRoleService, IOrganizeService organizeService)
        {
            _tkUserRepository = tkUserRepository;
            _tkUserMongoDbRepository = tkUserMongoDbRepository;
            _mechanismRepository = mechanismRepository;
            _mechanismMongoDbRepository = mechanismMongoDbRepository;
            _tkRoleService = tkRoleService;
            _organizeService = organizeService;
            _httpContext = App.HttpContext;
        }

        /// <summary>
        /// 获取用户类型下拉数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("getusertype")]
        public TkResult<List<EnumListDto>> GetAccountType()
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            if (authenticationType == "4" || authenticationType == "5")
                throw YNTKException.Oh(ErrorCode.D5015);
            var result = new List<EnumListDto>();
            if(authenticationType=="0" || authenticationType == "1")
            {
                result.Add(new EnumListDto() {Id="0",Value=0,Description="平台运营人员" });
                result.Add(new EnumListDto() {Id="1",Value=1,Description= "超级管理员" });
                result.Add(new EnumListDto() { Id = "2", Value = 2, Description = "组织管理员" });
                result.Add(new EnumListDto() { Id = "3", Value = 3, Description = "组织用户" });
                result.Add(new EnumListDto() { Id = "4", Value = 4, Description = "第三方用户" });
                result.Add(new EnumListDto() { Id = "5", Value = 5, Description = "游客用户" });
            }
            else
            {
                result.Add(new EnumListDto() { Id = "2", Value = 2, Description = "组织管理员" });
                result.Add(new EnumListDto() { Id = "3", Value = 3, Description = "组织用户" });
                result.Add(new EnumListDto() { Id = "4", Value = 4, Description = "第三方用户" });
            }
            return TkResult<List<EnumListDto>>.Success(result);
        }

        /// <summary>
        /// 获取用户下拉数据(排除自己和禁用的用户)
        /// </summary>
        /// <param name="mechanismId">机构id</param>
        /// <param name="roleId">角色id</param>
        /// <returns></returns>
        [HttpGet("gets/selects")]
        public async Task<TkResult<List<TkUserSelectListDto>>> GetSelect(string mechanismId,string roleId)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                Expression<Func<UserEntity, bool>> where = m => m.DeleteMark == null && 
                m.Id!=userId && m.EnabledMark==1 && m.OrganizeId== organizeId;
                if (!string.IsNullOrWhiteSpace(mechanismId))
                {
                    string queryMechanismId = await GetMechanismIdAsync(mechanismId, organizeId);
                    where = where.And(m => m.MechanismId == queryMechanismId);
                }
                if (!string.IsNullOrWhiteSpace(roleId)) where = where.And(m => m.RoleId == roleId);
                //从从mongodb中获取
                var users = await _tkUserMongoDbRepository.GetListAsync(_users, where);
                //再从sqlserver中获取
                if (!users.Any()) users = await _tkUserRepository.Entities.Where(where).ToListAsync();
                var result = users.Adapt<List<TkUserSelectListDto>>();
                return TkResult<List<TkUserSelectListDto>>.Success(result);
            }
            catch (Exception)
            {
                throw YNTKException.Oh("获取用户下拉数据(排除自己和禁用的用户)发生异常");
            }
        }

        /// <summary>
        /// 分页获取用户数据
        /// </summary>
        /// <param name="query">查询用户请求模型</param>
        /// <returns></returns>
        [HttpPost("gets/tkusers")]
        public async Task<TkPageResult<TkUserListDto>> Gets([FromBody] QueryTkUsersFilterRequestModel query)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D5015);

                #region 拼接查询条件
                Expression<Func<UserEntity, bool>> where = m => m.DeleteMark == null;
                if (query.enabledMark == 1) where = where.And(m => m.EnabledMark == 1);
                if (query.enabledMark == 0) where = where.And(m => m.EnabledMark != 1);
                if (authenticationType == "0" || authenticationType == "1")
                    where = where.And(m=>m.AccountType!=3);
                if(authenticationType == "2" || authenticationType == "3")
                    where = where.And(m => m.OrganizeId== organizeId);
                if (!string.IsNullOrWhiteSpace(query.organizeId))
                    where = where.And(m=> m.OrganizeId == query.organizeId);
                if (!string.IsNullOrWhiteSpace(query.mechanismId))
                {
                    string queryMechanismId = await GetMechanismIdAsync(query.mechanismId, organizeId);
                    where = where.And(m => m.MechanismId == queryMechanismId);
                }
                if (!string.IsNullOrWhiteSpace(query.roleId)) where = where.And(m=>m.RoleId==query.roleId);
                if (!string.IsNullOrWhiteSpace(query.keyword))
                    where = where.And(m=> m.Account.Contains(query.keyword) || m.RealName.Contains(query.keyword) || 
                    m.CertificatesNumber.Contains(query.keyword) || m.MobilePhone.Contains(query.keyword) || 
                    m.Email.Contains(query.keyword) || m.Description.Contains(query.keyword));
                if (query.accountType != null) where = where.And(m=>m.AccountType==query.accountType);
                if (query.noRole) where = where.And(m=> m.RoleId==null || m.RoleId=="");
                #endregion

                var pageList = new SqlSugarPagedList<TkUserListDto>();

                #region 先从mongodb中获取用户数据
                //排序生成器
                var builderSort = Builders<UserEntity>.Sort;
                //排序约束   Ascending 正序    Descending 倒序
                var sort = builderSort.Ascending(r=>r.SortCode).Descending(r => r.CreatorTime);
                //Item1.结果集 Item2.总条数 Item3.总页数
                (List<UserEntity>, int, int) result =
                    await _tkUserMongoDbRepository.GetListAsync(_users,
                    where, query.currentPage, query.pageSize, null, sort);
                pageList.list = result.Item1.Adapt<List<TkUserListDto>>();
                pageList.pagination = new PagedModel()
                {
                    PageIndex = query.currentPage,
                    PageSize = query.pageSize,
                    Total = result.Item2,
                    PageCount = result.Item3
                };
                #endregion

                if (!pageList.list.Any())
                {
                    #region 再从sqlserver中获取用户数据
                    var sqlResult = await _tkUserRepository.Entities.Where(where)
                        .OrderBy(r => r.SortCode, OrderByType.Asc)
                        .OrderBy(r => r.CreatorTime, OrderByType.Desc)
                        .ToPagedListAsync(query.currentPage, query.pageSize);
                    pageList.list = sqlResult.list.Adapt<List<TkUserListDto>>();
                    pageList.pagination = sqlResult.pagination;
                    #endregion
                }

                #region 处理返回用户数据
                if(pageList.list.Any())
                {
                    var orgIds = pageList.list.Select(r => r.organizeId).Distinct().ToList();
                    var orgs = await _organizeService.GetOrganizeListByIds(orgIds);
                    var mechanismIds = pageList.list.Where(r => !string.IsNullOrWhiteSpace(r.mechanismId))
                         ?.Select(r => r.mechanismId.Split(',').ToList())
                         ?.SelectMany(r => r).Distinct().ToList();
                    var mechanisms = await GetMechanismListAsync("", mechanismIds);
                    var roleIds= pageList.list.Where(r=>!string.IsNullOrWhiteSpace(r.roleId))
                        ?.Select(r => r.roleId).Distinct().ToList();
                    var roles = await _tkRoleService.GetTkRoleListByIdsAsync(roleIds);
                    foreach (var item in pageList.list)
                    {
                        item.accountTypeText = Shipeng.Util.EnumHelper
                            .GetEnumDescriptionString(item.accountType, typeof(AccountType));
                        if (!string.IsNullOrWhiteSpace(item.organizeId))
                            item.organizeName = orgs?.FirstOrDefault(r => r.Id == item.organizeId)?.FullName;
                        if (!string.IsNullOrWhiteSpace(item.mechanismId))
                        {
                            item.mechanismName = string.Join('/', mechanisms
                                ?.Where(r => item.mechanismId.Split(',').ToList().Contains(r.Id))
                                ?.Select(r => r.Name)?.ToList()).Split('/').Last();
                        }
                        if (!string.IsNullOrWhiteSpace(item.roleId))
                            item.roleName = roles?.FirstOrDefault(r => r.Id == item.roleId)?.Name;
                    }
                }
                #endregion
                return TkPageResult<TkUserListDto>.Success(pageList);
            }
            catch (Exception)
            {
                throw YNTKException.Oh("分页获取用户数据发生异常");
            }
        }

        /// <summary>
        /// 获取用户详细信息
        /// </summary>
        /// <param name="id">用户id</param>
        /// <returns></returns>
        [HttpGet("get/userinfo/{id}")]
        public async Task<TkResult<TkUserInfoDto>> Get([Required] string id)
        {
            var entity = await GetUserInfoAsync(u => u.Id == id && u.DeleteMark==null);
            var output = entity.Adapt<TkUserInfoDto>();
            if (output != null)
            {
                output.thirdParty = output.accountType == 4;
                output.accountTypeText = Shipeng.Util.EnumHelper
                            .GetEnumDescriptionString(output.accountType, typeof(AccountType));
                if(!string.IsNullOrWhiteSpace(output.organizeId) && output.organizeId!= "org00000000")
                    output.organizeName = (await _organizeService.GetOrganizeListByIds
                        (new List<string>(){ output.organizeId }))?[0].FullName;
                if (!string.IsNullOrWhiteSpace(output.mechanismId) && output.mechanismId != "jg000000")
                {
                    var mechanismIds = output.mechanismId.Split(',').ToList();
                    output.mechanismName = string.Join('/', (await GetMechanismListAsync("",mechanismIds))
                        ?.Select(r => r.Name)?.ToList()).Split('/').Last();
                }
                if (!string.IsNullOrWhiteSpace(output.roleId))
                    output.roleName = (await _tkRoleService.GetTkRoleListByIdsAsync
                        (new List<string>() { output.roleId }))?[0].Name;
                output.genderText=output.gender==null ? "" :
                    Shipeng.Util.EnumHelper.GetEnumDescriptionString((int)output.gender, typeof(Gender));
            }
            return TkResult<TkUserInfoDto>.Success(output);
        }

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="input">添加用户请求模型</param>
        /// <returns></returns>
        [HttpPost("add/user")]
        public async Task Create([FromBody] AddUserRequestModel input)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            if (authenticationType == "4" || authenticationType == "5")
                throw YNTKException.Oh(ErrorCode.D5015);

            #region 确认用户身份
            var entity = input.Adapt<UserEntity>();
            if(authenticationType == "0" || authenticationType == "1")
            {              
                if (input.thirdParty)
                {
                    //运营平台添加第三方用户
                    entity.AccountType = AccountType.ThirdPartyUser.GetHashCode();
                    entity.OrganizeId = organizeId;
                }
                else if(input.organizeId!=organizeId && !input.thirdParty)
                {
                    //运营平台添加组织管理员用户
                    if((await GetUserInfoAsync(u=>u.AccountType==2 && 
                    u.OrganizeId== input.organizeId && u.DeleteMark==null))!=null)
                        throw YNTKException.Oh(ErrorCode.D5021);
                    entity.AccountType = AccountType.OrganizationAdmin.GetHashCode();
                    entity.OrganizeId = input.organizeId;
                }
                else
                {
                    //添加运营平台用户
                    entity.AccountType = AccountType.None.GetHashCode();
                    entity.OrganizeId = organizeId;
                }              
            }
            else
            {
                //组织添加用户
                //if(input.thirdParty) throw YNTKException.Oh(ErrorCode.D5016);
                if (input.organizeId != organizeId) entity.OrganizeId = organizeId;
                if(input.thirdParty) entity.AccountType = AccountType.ThirdPartyUser.GetHashCode();
                else entity.AccountType = AccountType.OrganizationUser.GetHashCode();
            }
            #endregion

            #region 唯一信息验证
            if ((await GetUserInfoAsync(u=>u.Account==input.account && u.DeleteMark==null))!=null)
                throw YNTKException.Oh(ErrorCode.D5000);
            if (!string.IsNullOrWhiteSpace(input.mobilePhone) && 
                (await GetUserInfoAsync(u => u.MobilePhone == input.mobilePhone && u.DeleteMark == null))!=null)
                throw YNTKException.Oh(ErrorCode.D5017);
            if (!string.IsNullOrWhiteSpace(input.certificatesNumber) &&
              (await GetUserInfoAsync(u => u.CertificatesNumber == input.certificatesNumber && u.DeleteMark == null))!=null)
                throw YNTKException.Oh(ErrorCode.D5018);
            if (!string.IsNullOrWhiteSpace(input.email) &&
              (await GetUserInfoAsync(u => u.Email == input.email && u.DeleteMark == null)) != null)
                throw YNTKException.Oh(ErrorCode.D5019);
            #endregion

            entity.Secretkey = Guid.NewGuid().ToString();
            entity.Password = MD5Encryption.Encrypt(CommonConst.DEFAULT_PASSWORD + entity.Secretkey);
            //sqlserver保存用户信息
            var isOk = await _tkUserRepository.Context.Insertable(entity)
               .CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
            _ = isOk ?? throw YNTKException.Oh(ErrorCode.D5001);

            //mongodb保存用户信息
            entity = isOk;
            var result = await _tkUserMongoDbRepository.AddAsync(entity, _users);
            if (!result) throw YNTKException.Oh(ErrorCode.D5036);

            #region 同步员工信息
            if (entity.AccountType!=4 && entity.AccountType != 5)
            {
                await Event.EmitAsync("Employee:Add", new EmployeesEntity()
                {
                    Id = isOk.Id,
                    OrganizeId = entity.OrganizeId,
                    MechanismId = entity.MechanismId,
                    RoleId = entity.RoleId,
                    Account = entity.Account,
                    RealName = entity.RealName,
                    CertificatesNumber = entity.CertificatesNumber,
                    MobilePhone = entity.MobilePhone,
                    Email = entity.Email,
                    CreatorTime = isOk.CreatorTime
                });
            }
            #endregion
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="input">修改用户请求模型</param>
        /// <returns></returns>
        [HttpPut("update/user")]
        public async Task Update([FromBody] UpdateUserRequestModel input)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            var userId = user.Value;
            string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            if (authenticationType == "4" || authenticationType == "5")
                throw YNTKException.Oh(ErrorCode.D5015);
            var entity = await GetUserInfoAsync(r => r.Id == input.id && r.DeleteMark == null);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.D5002);

            #region 确认用户身份
            //var entity = input.Adapt<UserEntity>();
            entity = input.Mapper(entity);
            if (authenticationType == "0" || authenticationType == "1")
            {
                if (entity.AccountType == AccountType.Administrator.GetHashCode())
                {
                    if(entity.Id!= userId) throw YNTKException.Oh(ErrorCode.D5023);
                    //超级管理员修改自己的信息
                    entity.AccountType = AccountType.Administrator.GetHashCode();
                    entity.OrganizeId = organizeId;
                }
                else if (input.thirdParty)
                {
                    //运营平台添加第三方用户
                    entity.AccountType = AccountType.ThirdPartyUser.GetHashCode();
                    entity.OrganizeId = organizeId;
                }
                else if (input.organizeId != organizeId && !input.thirdParty)
                {
                    //运营平台修改组织管理员用户
                    if ((await GetUserInfoAsync(u => u.AccountType == 2 && 
                    u.OrganizeId == input.organizeId && u.Id!=input.id && u.DeleteMark == null))!=null)
                        throw YNTKException.Oh(ErrorCode.D5021);
                    entity.AccountType = AccountType.OrganizationAdmin.GetHashCode();
                    entity.OrganizeId = input.organizeId;
                }
                else
                {
                    //修改运营平台用户
                    if (entity.OrganizeId != organizeId) throw YNTKException.Oh(ErrorCode.D1016);
                    entity.AccountType = AccountType.None.GetHashCode();
                    entity.OrganizeId = organizeId;
                }
            }
            else
            {
                if (entity.OrganizeId != organizeId) throw YNTKException.Oh(ErrorCode.D1016);
                //组织修改用户
                if (entity.AccountType== AccountType.OrganizationAdmin.GetHashCode())
                    throw YNTKException.Oh(ErrorCode.D5020);
               // if (input.thirdParty) throw YNTKException.Oh(ErrorCode.D5016);
               //if (input.organizeId != organizeId) entity.OrganizeId = organizeId;
                if (input.thirdParty) entity.AccountType = AccountType.ThirdPartyUser.GetHashCode();
                else entity.AccountType = AccountType.OrganizationUser.GetHashCode();
            }
            #endregion

            #region 唯一信息验证
            if ((await GetUserInfoAsync(u => u.Account == input.account && u.Id!=input.id && u.DeleteMark == null))!=null)
                throw YNTKException.Oh(ErrorCode.D5000);
            if (!string.IsNullOrWhiteSpace(input.mobilePhone) &&
                (await GetUserInfoAsync(u => u.MobilePhone == input.mobilePhone && u.Id != input.id && u.DeleteMark == null))!=null)
                throw YNTKException.Oh(ErrorCode.D5017);
            if (!string.IsNullOrWhiteSpace(input.certificatesNumber) &&
              (await GetUserInfoAsync(u => u.CertificatesNumber == input.certificatesNumber && u.Id != input.id && u.DeleteMark == null))!=null)
                throw YNTKException.Oh(ErrorCode.D5018);
            if (!string.IsNullOrWhiteSpace(input.email) &&
              (await GetUserInfoAsync(u => u.Email == input.email && u.Id != input.id && u.DeleteMark == null))!=null)
                throw YNTKException.Oh(ErrorCode.D5019);
            #endregion

            entity.LastModifyTime = DateTime.Now;
            entity.LastModifyUserId = userId;
            //sqlserver保存用户信息
            var isOK = await _tkUserRepository.Context.Updateable(entity).ExecuteCommandAsync();
            if (!(isOK > 0))
                throw YNTKException.Oh(ErrorCode.D5004);

            //mongodb保存用户信息
            var update = await _tkUserMongoDbRepository.UpdateAsync(entity, _users, m => m.Id == entity.Id);
            if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.D5036);

            #region 同步员工信息
            if (entity.AccountType != 4 && entity.AccountType != 5)
            {
                await Event.EmitAsync("Employee:Update", new EmployeesEntity()
                {
                    Id = entity.Id,
                    OrganizeId = entity.OrganizeId,
                    MechanismId = entity.MechanismId,
                    RoleId = entity.RoleId,
                    Account = entity.Account,
                    RealName = entity.RealName,
                    CertificatesNumber = entity.CertificatesNumber,
                    MobilePhone = entity.MobilePhone,
                    Email = entity.Email,
                    CreatorTime = entity.CreatorTime,
                    LastModifyTime=entity.LastModifyTime
                });
            }
            #endregion
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="id">用户id</param>
        /// <returns></returns>
        [HttpDelete("delete/user/{id}")]
        public async Task Delete([Required] string id)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            if (authenticationType == "4" || authenticationType == "5")
                throw YNTKException.Oh(ErrorCode.D5015);
            var userInfo = await GetUserInfoAsync(r => r.Id ==id && r.DeleteMark == null);
            if (userInfo == null) throw YNTKException.Oh(ErrorCode.D5002);
            if(userInfo.AccountType == AccountType.Administrator.GetHashCode()) 
                throw YNTKException.Oh(ErrorCode.D1014);

            if (authenticationType == "2" || authenticationType == "3")
            {
                //组织删除用户
                if (userInfo.OrganizeId != organizeId) throw YNTKException.Oh(ErrorCode.D1016);
                if (userInfo.AccountType == AccountType.OrganizationAdmin.GetHashCode())
                    throw YNTKException.Oh(ErrorCode.D5024);
                //if (userInfo.AccountType == AccountType.ThirdPartyUser.GetHashCode()) 
                //    throw YNTKException.Oh(ErrorCode.D5025);
            }

            //sqlserver删除用户
            var isOk = await _tkUserRepository.Context.Deleteable(userInfo).ExecuteCommandAsync();
            if (!(isOk > 0))
                throw YNTKException.Oh(ErrorCode.D5026);

            //mongodb删除用户
            var delete = await _tkUserMongoDbRepository.DeleteAsync(_users, m => m.Id == id);
            if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.D5037);

            #region 同步员工信息
            if (userInfo.AccountType != 4 && userInfo.AccountType != 5)
            {
                await Event.EmitAsync("Employee:Delete", id);
            }
            #endregion
        }

        /// <summary>
        /// 更新用户状态(启用/禁用)
        /// </summary>
        /// <param name="id">角色id</param>
        /// <returns></returns>
        [HttpPut("state/{id}")]
        public async Task UpdateState([Required] string id)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            var userId = user.Value;
            string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            if (authenticationType == "4" || authenticationType == "5")
                throw YNTKException.Oh(ErrorCode.D5015);
            var entity = await GetUserInfoAsync(r => r.Id == id && r.DeleteMark == null);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.D5002);
            if (entity.AccountType == AccountType.Administrator.GetHashCode())
                throw YNTKException.Oh(ErrorCode.D1015);

            if (authenticationType == "2" || authenticationType == "3")
            {                
                if (entity.OrganizeId!= organizeId) throw YNTKException.Oh(ErrorCode.D1016);
                if (entity.AccountType == AccountType.OrganizationAdmin.GetHashCode())
                    throw YNTKException.Oh(ErrorCode.D5027);
                //if (entity.AccountType == AccountType.ThirdPartyUser.GetHashCode())
                //    throw YNTKException.Oh(ErrorCode.D5028);
            }

            //sqlserver更新用户状态
            var isOk = await _tkUserRepository.Context.Updateable<UserEntity>()
                .SetColumns(it => new UserEntity()
            {
                EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1),
                LastModifyUserId = userId,
                LastModifyTime = SqlFunc.GetDate()
            }).Where(it => it.Id == id).ExecuteCommandAsync();
            if (!(isOk > 0))
                throw YNTKException.Oh(ErrorCode.D5005);

            //mongodb更新用户状态
            entity.EnabledMark = entity.EnabledMark == 1 ? 0 : 1;
            entity.LastModifyTime = DateTime.Now;
            entity.LastModifyUserId = userId;
            var update = await _tkUserMongoDbRepository.UpdateAsync(entity, _users, m => m.Id == entity.Id);
            if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.D5038);
        }

        /// <summary>
        /// 角色管理分配用户专用接口
        /// </summary>
        /// <param name="input">角色管理分配用户专用模型</param>
        /// <returns></returns>
        [HttpPut("authorization")]
        public async Task AuthorizationUsers([FromBody] RoleDistributionUserRequestModel input)
        {
            if(input.userIds==null || input.userIds.Count<=0)
                throw YNTKException.Oh("请至少选择一个授权用户");
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            var userId = user.Value;
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            if (authenticationType == "4" || authenticationType == "5")
                throw YNTKException.Oh(ErrorCode.D1016);
            var role = (await _tkRoleService.GetTkRoleListByIdsAsync(new List<string>(){ input.id }))?[0];
            if (role == null) throw YNTKException.Oh(ErrorCode.D1608);

            var users = await GetUserListAsync(u => input.userIds.Contains(u.Id) && 
            string.IsNullOrWhiteSpace(u.RoleId) && u.DeleteMark == null);
            if(users==null || users.Count<=0) throw YNTKException.Oh("用户不存在");

            users.ForEach(item => {
                item.RoleId = input.id;
            });
            var isOk=await _tkUserRepository.UpdateAsync(users);
            if (!(isOk > 0))
                throw YNTKException.Oh(ErrorCode.D5029);

            var update=await _tkUserMongoDbRepository.UpdateManayAsync(users, _users);
            if (!(update > 0))
                throw YNTKException.Oh(ErrorCode.D5039);

            #region 同步员工信息
            users = users.Where(r => r.AccountType != 4 && r.AccountType != 5).ToList();
            if (users.Any())
            {
                await Event.EmitAsync("Employee:AuthorizationUsers", users);
            }
            #endregion
        }

        /// <summary>
        /// 用户管理分配角色专用接口
        /// </summary>
        /// <param name="input">用户管理分配角色请求模型</param>
        /// <returns></returns>
        [HttpPut("authorization/role")]
        public async Task AuthorizationRole([FromBody] TkUserAuthorizationRequestModel input)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            var userId = user.Value;
            string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            if (authenticationType == "4" || authenticationType == "5")
                throw YNTKException.Oh(ErrorCode.D1016);
            var role = (await _tkRoleService.GetTkRoleListByIdsAsync(new List<string>() { input.roleId }))?[0];
            if (role == null) throw YNTKException.Oh(ErrorCode.D1608);

            var userInfo = await GetUserInfoAsync(r => r.Id == input.id && r.DeleteMark == null);
            if (userInfo == null) throw YNTKException.Oh(ErrorCode.D5002);
            if (userInfo.AccountType == AccountType.Administrator.GetHashCode() && authenticationType!="0")
                throw YNTKException.Oh(ErrorCode.D1010);

            if(authenticationType == "2" || authenticationType == "3")
            {
                if (userInfo.OrganizeId != organizeId) throw YNTKException.Oh(ErrorCode.D1016);
                if (userInfo.AccountType == AccountType.OrganizationAdmin.GetHashCode())
                    throw YNTKException.Oh(ErrorCode.D5030);
                //if (userInfo.AccountType == AccountType.ThirdPartyUser.GetHashCode())
                //    throw YNTKException.Oh(ErrorCode.D5031);
            }
            userInfo.RoleId = input.roleId;
            var isOk = await _tkUserRepository.UpdateAsync(userInfo);
            if (!(isOk > 0))
                throw YNTKException.Oh(ErrorCode.D5029);

            var update = await _tkUserMongoDbRepository.UpdateAsync(userInfo, _users, m => m.Id == userInfo.Id);
            if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.D5039);

            #region 同步员工信息
            if (userInfo.AccountType != 4 && userInfo.AccountType != 5)
            {
                await Event.EmitAsync("Employee:AuthorizationRole", userInfo);
            }
            #endregion
        }

        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="id">用户id</param>
        /// <returns></returns>
        [HttpPut("resetpassword/{id}")]
        public async Task ResetPassword([Required] string id)
        {
            var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
            var userId = user.Value;
            string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
            var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
            //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
            if (authenticationType == "4" || authenticationType == "5")
                throw YNTKException.Oh(ErrorCode.D1016);

            var entity = await GetUserInfoAsync(u => u.Id == id && u.DeleteMark == null);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.D5002);
            if (entity.AccountType == AccountType.Administrator.GetHashCode())
                throw YNTKException.Oh(ErrorCode.D5032);

            if (authenticationType == "2" || authenticationType == "3")
            {
                if (entity.OrganizeId != organizeId) throw YNTKException.Oh(ErrorCode.D1016);
                if (entity.AccountType == AccountType.OrganizationAdmin.GetHashCode())
                    throw YNTKException.Oh(ErrorCode.D5033);
                //if (entity.AccountType == AccountType.ThirdPartyUser.GetHashCode())
                //    throw YNTKException.Oh(ErrorCode.D5034);
            }

            string secretkey = Guid.NewGuid().ToString();
            string password = MD5Encryption.Encrypt(CommonConst.DEFAULT_PASSWORD + secretkey);
            entity.Secretkey = secretkey;
            entity.Password = password;
            entity.ChangePasswordDate = DateTime.Now;
            entity.LastModifyTime = DateTime.Now;
            entity.LastModifyUserId = userId;
            var isOk = await _tkUserRepository.Context.Updateable(entity).ExecuteCommandAsync();
            if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.D5040);

            var update = await _tkUserMongoDbRepository.UpdateAsync(entity, _users, m => m.Id == entity.Id);
            if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.D5041);

            //强制将用户提掉线
        }

        /// <summary>
        /// 用户重置密码
        /// </summary>
        /// <param name="input">用户重置密码请求模型</param>
        /// <returns></returns>
        [HttpPut("resetpassword/user")]
        public async Task UserResetPassword([FromBody] ResetPasswordRequestModel input)
        {
            var userId = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID)?.Value;
            if(userId!=input.id) throw YNTKException.Oh(ErrorCode.D5002);
            var entity = await GetUserInfoAsync(u => u.Id == input.id && u.DeleteMark == null);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.D5002);
            if (input.id == "@yntk@super@admin") throw YNTKException.Oh(ErrorCode.D5032);

            //获取加密后的密码
            string encryptPasswod = MD5Encryption.Encrypt(input.oldPassword + entity.Secretkey);
            if(entity.Password!= encryptPasswod) throw YNTKException.Oh(ErrorCode.D5007);

            string secretkey = Guid.NewGuid().ToString();
            string password = MD5Encryption.Encrypt(input.newPassword + secretkey);
            entity.Secretkey = secretkey;
            entity.Password = password;
            entity.ChangePasswordDate = DateTime.Now;
            entity.LastModifyTime = DateTime.Now;
            entity.LastModifyUserId = userId;
            var isOk = await _tkUserRepository.Context.Updateable(entity).ExecuteCommandAsync();
            if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.D5040);

            var update = await _tkUserMongoDbRepository.UpdateAsync(entity, _users, m => m.Id == entity.Id);
            if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.D5041);
        }

        /// <summary>
        /// 用户设置系统主题
        /// </summary>
        /// <param name="input">用户设置系统主题请求模型</param>
        /// <returns></returns>
        [HttpPut("set/theme")]
        public async Task SetTheme([FromBody] SetThemeRequestModel input)
        {
            var userId = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID)?.Value;
            var entity = await GetUserInfoAsync(u => u.Id == userId && u.DeleteMark == null);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.D5002);
            entity.Language = input.language;
            entity.Theme = input.theme;
            entity.BackgroundColor = input.backgroundColor;
            entity.NavigationTextColor = input.navigationTextColor;
            await _tkUserRepository.Context.Updateable(entity).ExecuteCommandAsync();
            await _tkUserMongoDbRepository.UpdateAsync(entity, _users, m => m.Id == entity.Id);
        }

        /// <summary>
        /// 获取当前登录用户系统主题设置信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("get/theme")]
        public async Task<TkResult<ThemeDto>> GetTheme()
        {
            var userId = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID)?.Value;
            var entity = await GetUserInfoAsync(u => u.Id == userId && u.DeleteMark == null);
            _ = entity ?? throw YNTKException.Oh(ErrorCode.D5002);
            var result = new ThemeDto()
            {
                theme = entity.Theme == null ? "classic" : entity.Theme,//主题
                language = entity.Language,//系统语言
                backgroundColor = entity.BackgroundColor,//导航背景色
                navigationTextColor = entity.NavigationTextColor//导航文本色
            };
            return TkResult<ThemeDto>.Success(result);
        }


        /// <summary>
        /// 同步用户数据(开发人员同步专用)
        /// </summary>
        /// <param name="type">0.sqlserver同步mongodb 1.mongodb同步sqlserver</param>
        /// <param name="organizeId">要同步的组织id</param>
        /// <returns></returns>
        [HttpPut("synchronous/{type}")]
        public async Task Synchronous([Required] int type, string organizeId)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType != "1" || (type != 0 && type != 1)) throw YNTKException.Oh(ErrorCode.D1016);

                _tkUserRepository.Ado.BeginTran();
                List<UserEntity> entities = null;
                Expression<Func<UserEntity, bool>> where = r => r.DeleteMark == null;
                if (!string.IsNullOrWhiteSpace(organizeId)) where = where.And(r => r.OrganizeId == organizeId);
                if (type == 0)
                {
                    entities = await _tkUserRepository.Entities.Where(where).ToListAsync();
                    if (entities.Any())
                    {
                        //删除mongodb原数据
                        await _tkUserMongoDbRepository.DeleteAsync(_users, where);
                        //保存到mongodb
                        var succeed = await _tkUserMongoDbRepository.AddListAsync(entities, _users);
                        if (!succeed) throw YNTKException.Oh("用户数据sqlserver同步mongodb失败");
                    }
                }
                else
                {
                    entities = await _tkUserMongoDbRepository.GetListAsync(_users, where);
                    if (entities.Any())
                    {
                        //删除sqlserver原数据
                        await _tkUserRepository.DeleteAsync(where);
                        //保存到sqlserver                 
                        var isOk = await _tkUserRepository.Context.Insertable(entities).ExecuteCommandAsync();
                        if (!(isOk > 0)) throw YNTKException.Oh("用户数据mongodb同步sqlserver失败");
                    }
                }
            }
            catch (Exception ex)
            {
                _tkUserRepository.Ado.RollbackTran();
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"同步用户数据发生异常：{ex.Message}");
            }
        }





        /// <summary>
        /// 获取机构数据
        /// </summary>
        /// <param name="organizeId">组织id</param>
        /// <param name="ids">机构id集合</param>
        /// <returns></returns>
        private async Task<List<MechanismEntity>> GetMechanismListAsync(string organizeId, List<string> ids)
        {
            var result = new List<MechanismEntity>();
            Expression<Func<MechanismEntity, bool>> where = r => r.DeleteMark == null;
            if (!string.IsNullOrWhiteSpace(organizeId))
                where = r => r.OrganizeId == organizeId;
            if (ids != null && ids.Count > 0)
                where = r => ids.Contains(r.Id);

            //从mongodb中获取机构数据
            result = await _mechanismMongoDbRepository.GetListAsync(_collectionName, where);
            if (result == null || result.Count <= 0)
            {
                //从sqlserver数据库中获取机构数据
                result = await _mechanismRepository.Entities.Where(where).ToListAsync();
            }
            return result;
        }

        /// <summary>
        /// 处理机构id拼接上所有父级id
        /// </summary>
        /// <param name="id">机构id</param>
        /// <param name="organizeId">组织id</param>
        /// <returns></returns>
        private async Task<string> GetMechanismIdAsync(string id, string organizeId)
        {
            if (id.Contains(",")) return id;
            var data = await _mechanismMongoDbRepository.GetListAsync(_collectionName, m => m.OrganizeId == organizeId && m.DeleteMark == null);
            if (!data.Any())
                data = await _mechanismRepository.Entities.Where(r => r.OrganizeId == organizeId && r.DeleteMark == null).ToListAsync();
            if (!data.Any()) return id;
            //获取所有上级包括自己
            data = data.TreeWhere(r => r.Id == id, r => r.Id, r => r.ParentId);
            //顺序反转
            data.Reverse();
            var ids = data.Select(r => r.Id).ToList();
            id = string.Join(',', ids);
            return id;
        }


        #region PublicMethod
        /// <summary>
        /// 根据条件获取用户信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        [NonAction]
        public async Task<UserEntity> GetUserInfoAsync(Expression<Func<UserEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _tkUserMongoDbRepository.GetAsync(_users, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _tkUserRepository.FirstOrDefaultAsync(where);
            return entity;
        }

        /// <summary>
        /// 根据用户ID获取用户信息
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        [NonAction]
        public UserEntity GetUserInfoById(string userId)
        {
            //从从mongodb中获取
            var entity = _tkUserMongoDbRepository.Get(_users, m => m.Id == userId && m.DeleteMark == null);
            //再从sqlserver中获取
            if (entity == null) entity =  _tkUserRepository.FirstOrDefault(u => u.Id == userId && u.DeleteMark == null);
            return entity;
        }

        /// <summary>
        /// 根据用户ID获取用户信息
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        [NonAction]
        public async Task<UserEntity> GetUserInfoByUserId(string userId)
        {
            //从从mongodb中获取
            var entity = await _tkUserMongoDbRepository.GetAsync(_users, m=>m.Id==userId && m.DeleteMark==null);
            //再从sqlserver中获取
            if (entity == null) entity = await _tkUserRepository.FirstOrDefaultAsync(u => u.Id == userId && u.DeleteMark == null);
            return entity;
        }

        /// <summary>
        /// 根据用户账户获取用户信息
        /// </summary>
        /// <param name="account">用户账户</param>
        /// <returns></returns>
        [NonAction]
        public async Task<UserEntity> GetUserInfoByAccount(string account)
        {
            //从从mongodb中获取
            var entity = await _tkUserMongoDbRepository.GetAsync(_users, m => m.Account == account && m.DeleteMark == null);
            //再从sqlserver中获取
            if (entity == null) entity = await _tkUserRepository.FirstOrDefaultAsync(u => u.Account == account && u.DeleteMark == null);
            return entity;
        }

        /// <summary>
        /// 根据账号和密码获取用户信息
        /// </summary>
        /// <param name="account">用户账户</param>
        /// <param name="password">用户密码</param>
        /// <returns></returns>
        [NonAction]
        public async Task<UserEntity> GetUserInfoByLoginAsync(string account, string password)
        {
            //从从mongodb中获取
            var entity = await _tkUserMongoDbRepository.GetAsync(_users, m => m.Account == account && m.Password==password && m.DeleteMark == null);
            //再从sqlserver中获取
            if (entity == null) entity = await _tkUserRepository.FirstOrDefaultAsync(u => u.Account == account && u.Password==password && u.DeleteMark == null);
            return entity;
        }

        /// <summary>
        /// 根据用户id集合获取用户数据
        /// </summary>
        /// <param name="ids">用户id集合</param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<UserEntity>> GetUserListByIds(List<string> ids)
        {
            var result = new List<UserEntity>();
            if (!ids.Any()) return result;
            //从从mongodb中获取
            result = await _tkUserMongoDbRepository.GetListAsync(_users, m=>ids.Contains(m.Id) && m.DeleteMark==null);
            //再从sqlserver中获取
            if (!result.Any()) result = await _tkUserRepository.Entities.Where(u=>ids.Contains(u.Id) && u.DeleteMark==null).ToListAsync();
            return result;
        }

        /// <summary>
        /// 根据条件获取用户数据
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<UserEntity>> GetUserListAsync(Expression<Func<UserEntity, bool>> where)
        {
            //从从mongodb中获取
            var result = await _tkUserMongoDbRepository.GetListAsync(_users, where);
            //再从sqlserver中获取
            if (!result.Any()) result = await _tkUserRepository.Entities.Where(where).ToListAsync();
            return result;
        }

        /// <summary>
        /// 用户被设置为机构主管更新用户所属机构
        /// </summary>
        /// <param name="userId">用户id</param>
        /// <param name="mechanismId">机构id</param>
        /// <returns></returns>
        [NonAction]
        public async Task UpdateUserMechanismAsync(string userId,string mechanismId)
        {
            var userInfo = await GetUserInfoAsync(r => r.Id == userId && r.DeleteMark == null);
            if (userInfo != null)
            {
                userInfo.MechanismId = mechanismId;
                userInfo.LastModifyTime = DateTime.Now;
                userInfo.LastModifyUserId = userId;
                await _tkUserRepository.Context.Updateable(userInfo).ExecuteCommandAsync();
                await _tkUserMongoDbRepository.UpdateAsync(userInfo, _users, m => m.Id == userInfo.Id);

                #region 同步员工信息
                if (userInfo.AccountType !=4 && userInfo.AccountType !=5)
                {
                    await Event.EmitAsync("Employee:Update", new EmployeesEntity()
                    {
                        Id = userInfo.Id,
                        OrganizeId = userInfo.OrganizeId,
                        MechanismId = userInfo.MechanismId,
                        RoleId = userInfo.RoleId,
                        Account = userInfo.Account,
                        RealName = userInfo.RealName,
                        CertificatesNumber = userInfo.CertificatesNumber,
                        MobilePhone = userInfo.MobilePhone,
                        Email = userInfo.Email,
                        CreatorTime = userInfo.CreatorTime,
                        LastModifyTime = userInfo.LastModifyTime
                    });
                }
                #endregion
            }
        }

        /// <summary>
        /// 批量添加用户
        /// </summary>
        /// <param name="entitys"></param>
        /// <returns></returns>
        [NonAction]
        public async Task BatchAddUsersAsync(List<UserEntity> entitys)
        {
            await _tkUserRepository.Context.Insertable(entitys).ExecuteReturnEntityAsync();
            await _tkUserMongoDbRepository.AddListAsync(entitys, _users);
        }
        #endregion

    }
}
